package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcCsunBodySensorLocationMapper;
import com.csun.cmny.provider.dao.DmcCsunNewBodyLocationMapper;
import com.csun.cmny.provider.device.csun.gateway.GatewayMessageSender;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.constant.DeviceConstant;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.device.DeviceBindDto;
import com.csun.cmny.provider.model.dto.newBody.BindCsunNewBodyLocationDto;
import com.csun.cmny.provider.model.dto.newBody.CsunNewBodyQueryDto;
import com.csun.cmny.provider.model.enums.bodysensor.DmcCsunBodySensorBindTypeEnum;
import com.csun.cmny.provider.model.enums.device.DeviceStatusEnum;
import com.csun.cmny.provider.model.vo.RoomBuildingVo;
import com.csun.cmny.provider.model.vo.life.DmcDeviceByRoom;
import com.csun.cmny.provider.model.vo.newBody.CsunNewBodyVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.DeviceUtils;
import com.csun.cmny.util.PubUtils;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-12-27 15:19
 * @Description:
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcCsunNewBodyLocationServiceImpl extends BaseService<DmcCsunNewBodyLocation>
        implements DmcCsunNewBodyLocationService {

    @Resource
    private DmcCsunNewBodyLocationMapper dmcCsunNewBodyLocationMapper;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private DmcCsunBodySensorLocationMapper dmcCsunBodySensorLocationMapper;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private DmcCsunGatewayConfigBodySensorService dmcCsunGatewayConfigBodySensorService;
    @Resource
    private DmcCsunBodySensorConfigService dmcCsunBodySensorConfigService;
    @Resource
    private OmcRpcService omcRpcService;
    @Resource
    private GatewayMessageSender gatewayMessageSender;
    @Resource
    private DmcCsunGatewayBindService dmcCsunGatewayBindService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private DmcDeviceAlertService dmcDeviceAlertService;
    @Resource
    private DmcDeviceOnlineRecordService dmcDeviceOnlineRecordService;
    @Resource
    private DeviceUtils deviceUtils;

    /**
     * query dmc csun newBody and location list with page
     *
     * @param csunNewBodyQueryDto the csun newBody query dto
     *
     * @return the list
     */
    @Override
    public List<CsunNewBodyVo> queryListWithPage(CsunNewBodyQueryDto csunNewBodyQueryDto) {

        PageHelper.startPage(csunNewBodyQueryDto.getPageNum(), csunNewBodyQueryDto.getPageSize());

        List<CsunNewBodyVo> csunNewBodyVos = dmcCsunNewBodyLocationMapper.queryListWithPage(csunNewBodyQueryDto);

        return csunNewBodyVos;
    }

    /**
     * delete dmc csun humidistat by id
     *
     * @param id the csun humidistat id
     *
     * @return the int.
     */
    @Override
    public Integer deleteById(Long id) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunNewBodySensorByDeviceId(id);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610027, id);
        }

        // 2.判断人体感应是否已经绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocationQuery = dmcCsunBodySensorLocationMapper
                .selectByPrimaryKey(id);
        if (PublicUtil.isNotEmpty(dmcCsunBodySensorLocationQuery)) {
            dmcCsunBodySensorLocationMapper.deleteByPrimaryKey(id);
        }

        // 判断是绑定了网关
        DmcCsunGatewayBind dmcCsunGatewayBind = new DmcCsunGatewayBind();
        dmcCsunGatewayBind.setDeviceId(id);
        int count = dmcCsunGatewayBindService.selectCount(dmcCsunGatewayBind);
        if (count > 0) {
            throw new DmcBizException(ErrorCodeEnum.DMC100614009);
        }

        // 3.删除设备
        return dmcDeviceService.deleteDmcDeviceById(id);
    }

    /**
     * bind dmc csun humidistat and location
     *
     * @param bindCsunNewBodyLocationDto the bind csun humidistat location
     * @param loginAuthDto                  the login auth dto
     *
     * @return the int
     */
    @Override
    public Integer bind(BindCsunNewBodyLocationDto bindCsunNewBodyLocationDto, LoginAuthDto loginAuthDto) {

        // 判断设备是否存在
        DmcDevice dmcDevice = dmcDeviceService
                .checkDeviceIsCsunNewBodySensorByDeviceId(bindCsunNewBodyLocationDto.getDeviceId());
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610027, bindCsunNewBodyLocationDto.getDeviceId());
        }

        // 2.校验人体感应是否已经被绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocationQuery = dmcCsunBodySensorLocationMapper
                .selectByPrimaryKey(bindCsunNewBodyLocationDto.getDeviceId());
        if (PublicUtil.isNotEmpty(dmcCsunBodySensorLocationQuery)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610028, dmcCsunBodySensorLocationQuery.getDeviceId(),
                    dmcCsunBodySensorLocationQuery.getLocation());
        }

        // 3.校验绑定类型
        Preconditions.checkArgument(!PubUtils.isNull(bindCsunNewBodyLocationDto.getBindType()),
                cmnyMessageSource.getMessage("csun.body.sensor.location.bind.type.null", null));

        Preconditions.checkArgument(bindCsunNewBodyLocationDto.getBindType() >= 0
                        && bindCsunNewBodyLocationDto.getBindType() <= 4,
                cmnyMessageSource.getMessage("csun.body.sensor.location.bind.type.range", null));

        // 4.校验位置
        Preconditions.checkArgument(!PubUtils.isNull(bindCsunNewBodyLocationDto.getLocation()),
                cmnyMessageSource.getMessage("csun.body.sensor.location.null", null));

        // 5.校验房间Id
        if (bindCsunNewBodyLocationDto.getBindType().equals(DmcCsunBodySensorBindTypeEnum.CUSTOM.getKey())) {

            /*
             * 2020-01-10
             * */
            // 删除已经下发的配置
            DmcCsunGatewayConfigBodySensor dmcCsunGatewayConfigBodySensor = new DmcCsunGatewayConfigBodySensor();
            dmcCsunGatewayConfigBodySensor.setDeviceId(bindCsunNewBodyLocationDto.getDeviceId());
            dmcCsunGatewayConfigBodySensorService.delete(dmcCsunGatewayConfigBodySensor);

            // 查询配置
            DmcCsunBodySensorConfig dmcCsunBodySensorConfig = dmcCsunBodySensorConfigService
                    .queryConfigByRoomIdAndGroupId(bindCsunNewBodyLocationDto.getDeviceId(),
                            0, dmcDevice.getGroupId());
            // TODO 设置配置

            // 发送配置
            if (PublicUtil.isNotEmpty(dmcCsunBodySensorConfig)) {
                gatewayMessageSender.setLifeBodySensorTimer(bindCsunNewBodyLocationDto.getDeviceId().toString(),
                        dmcCsunBodySensorConfig.getToiletAttentionTime().toString(), dmcCsunBodySensorConfig.getToiletWarningTime().toString(), dmcCsunBodySensorConfig.getToiletUnusualTime().toString());
            }
        }
        if (bindCsunNewBodyLocationDto.getBindType().equals(DmcCsunBodySensorBindTypeEnum.ROOM.getKey())) {
            // 绑定类型为房间
            Preconditions.checkArgument(!PubUtils.isNull(bindCsunNewBodyLocationDto.getRoomId()),
                    cmnyMessageSource.getMessage("csun.body.sensor.location.bind.room.id.null", null));
            // 校验房间Id是否存在
            // TODO 校验房间Id是否存在
            RoomBuildingVo roomBuildingVo = omcRpcService
                    .queryRoomBuildingByRoomId(bindCsunNewBodyLocationDto.getRoomId());
            if (PublicUtil.isEmpty(roomBuildingVo)) {
                // 房间不存在
                throw new DmcBizException(ErrorCodeEnum.DMC100610058);
            }
            bindCsunNewBodyLocationDto.setLocation(roomBuildingVo.getLocation());

            /*
             * 2020-01-10
             * */
            // 删除已经下发的配置
            DmcCsunGatewayConfigBodySensor dmcCsunGatewayConfigBodySensor = new DmcCsunGatewayConfigBodySensor();
            dmcCsunGatewayConfigBodySensor.setDeviceId(bindCsunNewBodyLocationDto.getDeviceId());
            dmcCsunGatewayConfigBodySensorService.delete(dmcCsunGatewayConfigBodySensor);

            // 查询配置
            DmcCsunBodySensorConfig dmcCsunBodySensorConfig = dmcCsunBodySensorConfigService
                    .queryConfigByRoomIdAndGroupId(bindCsunNewBodyLocationDto.getDeviceId(),
                            bindCsunNewBodyLocationDto.getRoomId(), dmcDevice.getGroupId());
            // TODO 设置配置

            // 发送配置
            if (PublicUtil.isNotEmpty(dmcCsunBodySensorConfig)) {
                gatewayMessageSender.setLifeBodySensorTimer(bindCsunNewBodyLocationDto.getDeviceId().toString(),
                        dmcCsunBodySensorConfig.getToiletAttentionTime().toString(), dmcCsunBodySensorConfig.getToiletWarningTime().toString(), dmcCsunBodySensorConfig.getToiletUnusualTime().toString());
            }
        }

        // 5.校验房间Id
        if (bindCsunNewBodyLocationDto.getBindType().equals(DmcCsunBodySensorBindTypeEnum.LIFE_ROOM.getKey())) {
            // 绑定类型为房间
            Preconditions.checkArgument(!PubUtils.isNull(bindCsunNewBodyLocationDto.getRoomId()),
                    cmnyMessageSource.getMessage("csun.body.sensor.location.bind.room.id.null", null));
            // 校验房间Id是否存在
            // TODO 校验房间Id是否存在
            RoomBuildingVo roomBuildingVo = omcRpcService
                    .queryRoomBuildingByRoomId(bindCsunNewBodyLocationDto.getRoomId());
            if (PublicUtil.isEmpty(roomBuildingVo)) {
                // 房间不存在
                throw new DmcBizException(ErrorCodeEnum.DMC100610058);
            }

            /**
             * @date    2020-04-24
             * @author  chisj
             * @desc    一个房间只能绑定一个新人感
             */
            DmcCsunBodySensorLocation record = new DmcCsunBodySensorLocation();
            record.setRoomId(bindCsunNewBodyLocationDto.getRoomId());
            int count = dmcCsunBodySensorLocationMapper.selectCount(record);
            if (count > 0) {
                throw new DmcBizException(ErrorCodeEnum.DMC100614010);

            }

            /*
             * 2020-01-10
             * */
            // 删除已经下发的配置
            DmcCsunGatewayConfigBodySensor dmcCsunGatewayConfigBodySensor = new DmcCsunGatewayConfigBodySensor();
            dmcCsunGatewayConfigBodySensor.setDeviceId(bindCsunNewBodyLocationDto.getDeviceId());
            dmcCsunGatewayConfigBodySensorService.delete(dmcCsunGatewayConfigBodySensor);

            // 查询配置
            DmcCsunBodySensorConfig dmcCsunBodySensorConfig = dmcCsunBodySensorConfigService
                    .queryConfigByRoomIdAndGroupId(bindCsunNewBodyLocationDto.getDeviceId(),
                            bindCsunNewBodyLocationDto.getRoomId(), dmcDevice.getGroupId());
            // TODO 设置配置

            // 发送配置
            if (PublicUtil.isNotEmpty(dmcCsunBodySensorConfig)) {
                gatewayMessageSender.setLifeBodySensorTimer(bindCsunNewBodyLocationDto.getDeviceId().toString(),
                        dmcCsunBodySensorConfig.getToiletAttentionTime().toString(), dmcCsunBodySensorConfig.getToiletWarningTime().toString(), dmcCsunBodySensorConfig.getToiletUnusualTime().toString());
            }
        }

        // 6.添加绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocation = new DmcCsunBodySensorLocation();
        BeanUtils.copyProperties(bindCsunNewBodyLocationDto, dmcCsunBodySensorLocation);
        dmcCsunBodySensorLocation.setUpdateInfo(loginAuthDto);

        return dmcCsunBodySensorLocationMapper.insertSelective(dmcCsunBodySensorLocation);
    }

    /**
     * untied dmc csun humidistat and location
     *
     * @param deviceId the dmc csun humidistat id
     * @return the int
     */
    @Override
    public Integer untied(Long deviceId) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunNewBodySensorByDeviceId(deviceId);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610027, deviceId);
        }

        // 2.判断人体感应是否已经绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocationQuery = dmcCsunBodySensorLocationMapper
                .selectByPrimaryKey(deviceId);
        if (PublicUtil.isEmpty(dmcCsunBodySensorLocationQuery)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610029, deviceId);
        }

        // 3.解绑人体感应
        Integer result = dmcCsunBodySensorLocationMapper.deleteByPrimaryKey(deviceId);
        if (result > 0) {
//            if(dmcCsunBodySensorLocationQuery.getBindType().equals(DeviceConstant.DEVICE_BIND_TYPE_LIFE)){
                dmcDeviceAlertService.deleteByDeviceId(deviceId);
//            }

            //删除人感配置
            dmcCsunBodySensorConfigService.deleteByKey(deviceId);
            //删除redis中的是否在房间的状态
            redisTemplate.delete(RedisKeyUtil.getCsunBodySensorIsInRoomKey(dmcDevice.getDeviceNo()));
        }

        dmcDeviceOnlineRecordService.deleteByDeviceId(deviceId);

        return result;
    }

    @Override
    public List<Long> selectDeviceIdByRoomId(Long roomId) {
        return dmcCsunNewBodyLocationMapper.selectDeviceIdByRoomId(roomId);
    }

    @Override
    public DmcDeviceByRoom selectRoomIdByDeviceId(Long alertId) {
        return dmcCsunNewBodyLocationMapper.selectRoomIdByDeviceId(alertId);
    }

    @Override
    public List<CsunNewBodyVo> listGatewayBindBodySensor(Long deviceId) {

        List<CsunNewBodyVo> voList = dmcCsunNewBodyLocationMapper.listGatewayBindBodySensor(deviceId);

        for (CsunNewBodyVo chv : voList) {
            if (PublicUtil.isNotEmpty(chv.getBindType())) {
                // 设备绑定
                chv.setBind(true);
                DeviceBindDto deviceBindDto = new DeviceBindDto();
                BeanUtils.copyProperties(chv, deviceBindDto);
                RoomBuildingVo rbv = deviceUtils.getRoomBuildingVo(deviceBindDto);

                if (PublicUtil.isNotEmpty(rbv) && PublicUtil.isNotEmpty(rbv.getLocation())) {
                    chv.setLocation(rbv.getLocation());
                    chv.setBuildingName(rbv.getBuildingName());
                    chv.setFloorNo(rbv.getFloorNo());
                    chv.setRoomNo(rbv.getRoomNo());
                    chv.setOldmanId(rbv.getOldmanId());
                    chv.setOldmanName(rbv.getOldmanName());
                }
            }

            // 判断设备是否在线
            if (redisTemplate.hasKey(RedisKeyUtil.getCsunBodySensorOnline(chv.getDeviceNo()))) {
                chv.setStatus(DeviceStatusEnum.ONLINE.getKey());
            } else {
                chv.setStatus(DeviceStatusEnum.OFFLINE.getKey());
            }
        }

        return voList;
    }

    @Override
    public CsunNewBodyVo get(Long deviceId) {

        return dmcCsunNewBodyLocationMapper.get(deviceId);
    }
}
